﻿using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Boggle.Net.Model;
using Boggle.Net.ViewModels;
using Caliburn.Micro;

namespace Boggle.Net
{
    public abstract class BootstrapperBase : Bootstrapper<IShell>, IDisposable
    {
        CompositionContainer _container;

        public void Dispose()
        {
            if (_container == null) return;

            _container.Dispose();
            _container = null;
        }

        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
        protected override void Configure()
        {
            var catalog = new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)));

            _container = new CompositionContainer(catalog);

            var batch = new CompositionBatch();

            batch.AddExportedValue(EnhancedNorthAmericanBenchmarkWordList);
            batch.AddExportedValue<IWindowManager>(new WindowManager());
            batch.AddExportedValue<IEventAggregator>(new EventAggregator());
            batch.AddExportedValue(_container);
            batch.AddExportedValue(catalog);

            _container.Compose(batch);
        }

        protected override object GetInstance(Type serviceType, string key)
        {
            var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
            var instance = _container.GetExportedValues<object>(contract).FirstOrDefault();

            if (instance == null)
                throw new ApplicationException(string.Format("Could not locate any instances of contract {0}.", contract));

            return instance;
        }

        protected abstract IWordList EnhancedNorthAmericanBenchmarkWordList { get; }
    }
}
